﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;

namespace EMoney.IStock.Client.Framework
{
    /// <summary>
    /// 加解密类
    /// </summary>
    public class EncryptionUtil
    {
        //AES默认密钥向量 
        private static byte[] _key1 = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; 
        //private static byte[] _key1 = { 0x45, 0x39, 0x32, 0x42, 0x30, 0x38, 0x26, 0x21, 0x46, 0x37, 0x26, 0x24};//, 0x90, 0xAB, 0xCD, 0xEF }; 

        /// <summary>
        /// 公钥私钥信息
        /// </summary>
        public static readonly string key = "<RSAKeyValue><Modulus>tXD+BESPJ4fmhXvnxdxvTszWb/aSKnsICUcWqMf/4M2q22jIcWzxUcrZyZoszii5GCsbO1KuWXhHASvmrmI1C7OELDr4U/SraOCGr8+e/Sh4XzkDjyWq/0LmC3v0JPOo9bM92ZaDa0mFrnxSwAPY3iSat2evHto4IhIgBZkTXL8=</Modulus><Exponent>AQAB</Exponent><P>7HIYskmXkk560kZPo05PKltur1sQvWEg2f52UkHK6Br6SVUcbvzmXemKzL+ZhvUEOeC4pNih0YWf7rqhziLKgQ==</P><Q>xHJfmjUTKQJNryIcGiNiYgBOLfxe6vk2GB48JkeXuRMccoII7148RyJYSNLLArEepMDpLnwBAhQHTHvoqfoHPw==</Q><DP>vfzgA0JG3HTbE+MTUrE1w188jQKrbMCC2Scyg94B4Ibs3cfZ1QS5RnTF5sd94Yc3IhqDw1GelPC+FeE46p3iAQ==</DP><DQ>IpN67jpvP+WO5MddKOCXfWZOXFuyHSt18PLJZXduZf3OIP1wMylj9KU/4rlvT+761Ma7hBoBV2tNCZI5lklSow==</DQ><InverseQ>jiI30UoHc0qODB+DzDYYw1tDiclfbUwh9kl/V/OYDzVx/eOeL5JQhMDBopPFcgsO0/ik77J9aU1KMCnRUdgYZA==</InverseQ><D>UUPHcc/nMjRrKjQhzfv6GpgiH0mXk9FA+y7M1lGlqGFVeioHRM4fk5vAScx07u1MYafE7aANmOMHIl4wVsCDsvUT5HoWIZYfoh6YJrLheLD2Hj3i7MOq4Yg1dlnScjCQ+dZjOKrCWC7aoiBmXVJw8HHZqzGkCVLJnoktT8mmwwE=</D></RSAKeyValue>";

        /// <summary>
        /// 解密一个String使用RSA
        /// </summary>
        /// <param name="input">被解密的对象</param>
        /// <param name="key">私钥</param>
        /// <param name="encodingUsing">编码格式</param>
        /// <returns>解密后的字符串</returns>
        public static string Decrypt(string input, Encoding encodingUsing = null)
        {
            if (string.IsNullOrEmpty(input))
            {
                return string.Empty;
            }
            else
            {
                try
                {
                    using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
                    {
                        encodingUsing = encodingUsing ?? Encoding.UTF8;
                        rsa.FromXmlString(key);
                        var encryptedBytes = rsa.Decrypt(Convert.FromBase64String(input), false);
                        rsa.Clear();

                        return encodingUsing.GetString(encryptedBytes);
                    }
                }
                catch (Exception ex)
                {
                    LogManager.DefaultLogger.Error(ex, string.Concat("RSA解密失败",input));

                    return string.Empty;
                }                
            }
        }

        /// <summary>
        /// rsa 加密
        /// </summary>
        /// <param name="input"></param>
        /// <param name="encodingUsing"></param>
        /// <returns></returns>
        public static string Encrypt(string input, Encoding encodingUsing = null)
        {
            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                encodingUsing = encodingUsing ?? Encoding.UTF8;
                byte[] cipherbytes;
                rsa.FromXmlString(key);
                cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(input), false);
                rsa.Clear();
                return Convert.ToBase64String(cipherbytes);
            }
        }

        /// <summary>
        /// 取得公钥
        /// </summary>
        /// <returns>公钥队列</returns>
        public static List<string> GetJsPublicKey()
        {
            var list = new List<string>();
            var sb = new StringBuilder();

            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())
            {
                rsa.FromXmlString(key);
                // 取得公钥信息（false 公钥; true 公钥和私钥）
                var parameter = rsa.ExportParameters(false);
                foreach (var c in parameter.Exponent)
                {
                    sb.AppendFormat("{0:x2}", c);
                }

                list.Add(sb.ToString());
                sb.Clear();
                foreach (var c in parameter.Modulus)
                {
                    sb.AppendFormat("{0:x2}", c);
                }

                list.Add(sb.ToString());
                return list;
            }
        }

        #region #DES加解密
        private static string deskey = "TxCNCGdscofyMbZpklNtsVvn";//一定要放一个24位的KEY，这个KEY是用来加解密的
        //private static string deskey = "13D97C1C0758DA99734A329318E6DC1617FC89F8562F65D6";
        private static Encoding en = ASCIIEncoding.ASCII;
        //private static Encoding en = Encoding.ASCII;
        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="value">加密串</param>
        /// <returns>解密结果</returns>
        public static string DesDecoding(string value)
        {
            try
            {
                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();

                des.Key = en.GetBytes(deskey);
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.Zeros;
                ICryptoTransform DESDecrypt = des.CreateDecryptor();
                string result = "";

                byte[] Buffer = Convert.FromBase64String(value);
                result = en.GetString(DESDecrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
                return result.Replace("\0", "");
            }
            catch
            {
                return String.Empty;
            }
        }


        /// <summary>
        /// 加密
        /// </summary>
        /// <param name="value">需要加密的串</param>
        /// <returns>加密结果(BASE64编码格式)</returns>
        public static string DesEncoding(string value)
        {
            try
            {
                if (string.IsNullOrEmpty(value))
                {
                    return string.Empty;
                }

                TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
                des.Key = en.GetBytes(deskey);
                des.Mode = CipherMode.ECB;
                des.Padding = PaddingMode.Zeros;
                ICryptoTransform DESEncrypt = des.CreateEncryptor();
                byte[] Buffer = en.GetBytes(value);
                return Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer, 0, Buffer.Length));
            }
            catch
            {
                return String.Empty;
            }
        }
        #endregion

        #region 电信解密
        private static readonly string sKey = "13D97C1C0758DA99734A329318E6DC1617FC89F8562F65D6";
        private static readonly string sIv = "0102030405060708";

        public static string AdslDecry(string strTobeDeCrypted)
        {
            if (strTobeDeCrypted == "") return "";
            try
            {
                byte[] pKEY = HexStringToByteArray(sKey);
                byte[] pIV = HexStringToByteArray(sIv);
                byte[] Decrypted;

                if (Decrypt(pKEY, pIV, Convert.FromBase64String(strTobeDeCrypted), out Decrypted))
                {
                    return ConvertByteArrayToString(Decrypted);
                }
                else
                    return "";
            }
            catch { }
            return "";
        }
        private static string ConvertByteArrayToString(byte[] buf)
        {
            //return System.Text.Encoding.GetEncoding("utf-8").GetString(buf);
            return System.Text.Encoding.GetEncoding("gb2312").GetString(buf);
        }
        private static byte[] HexStringToByteArray(string s)
        {
            s = s.Replace(" ", "");
            byte[] buffer = new byte[s.Length / 2];
            for (int i = 0; i < s.Length; i += 2)
            {
                buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);
            }
            return buffer;
        }
        private static bool Decrypt(byte[] KEY, byte[] IV, byte[] TobeDecrypted, out  byte[] Decrypted)
        {
            var des = new TripleDESCryptoServiceProvider();
            Decrypted = null;

            try
            {
                byte[] tmpiv = { 0, 1, 2, 3, 4, 5, 6, 7 };
                for (int ii = 0; ii < 8; ii++)
                {
                    tmpiv[ii] = IV[ii];
                }
                byte[] tmpkey = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7 };
                for (int ii = 0; ii < 24; ii++)
                {
                    tmpkey[ii] = KEY[ii];
                }
                //tridesdecrypt.Dispose();				
                ICryptoTransform tridesdecrypt = des.CreateDecryptor(tmpkey, tmpiv);
                //tridesdecrypt = des.CreateDecryptor(KEY,tmpiv);
                Decrypted = tridesdecrypt.TransformFinalBlock(TobeDecrypted, 0, TobeDecrypted.Length);
                //tridesencrypt.Dispose();
                des.Clear();
            }
            catch (Exception)
            {
                //Console.WriteLine(e.ToString());
                return false;
            }
            return true;
        }
        #endregion

        #region AES加解密
        /// <summary>
        /// AES加密算法
        /// </summary>
        /// <param name="plainText">明文字符串</param>
        /// <param name="strKey">密钥</param>
        /// <returns>返回加密后的密文字节数组</returns>
        public static byte[] AESEncrypt(string plainText, string strKey)
        {
            //string temp = Encoding.Default.GetString(_key1.ToArray());
            //分组加密算法
            SymmetricAlgorithm des = Rijndael.Create();
            byte[] inputByteArray = Encoding.UTF8.GetBytes(plainText);//得到需要加密的字节数组	
            //设置密钥及密钥向量
            
            des.Key = Encoding.UTF8.GetBytes(strKey);
            //des.IV = _key1;
            des.Mode = CipherMode.ECB;
            des.BlockSize = 128;
            des.GenerateIV();

            MemoryStream ms = new MemoryStream();
            CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
            cs.Write(inputByteArray, 0, inputByteArray.Length);
            cs.FlushFinalBlock();
            byte[] cipherBytes = ms.ToArray();//得到加密后的字节数组
            cs.Close();
            ms.Close();
            return cipherBytes;
        }

        public static string EncryptMessage(string plainText, string key)
        {
            byte[] text = Encoding.Default.GetBytes(plainText);//得到需要加密的字节数组	
            RijndaelManaged aes = new RijndaelManaged();
            aes.KeySize = 128;
            aes.BlockSize = 128;
            aes.Padding = PaddingMode.Zeros;
            aes.Mode = CipherMode.CBC;

            aes.Key = Encoding.Default.GetBytes(key);
            aes.GenerateIV();

            string IV = ("-[--IV-[-" + Encoding.Default.GetString(aes.IV));

            ICryptoTransform AESEncrypt = aes.CreateEncryptor(aes.Key, aes.IV);
            byte[] buffer = text;

            return Convert.ToBase64String(Encoding.Default.GetBytes(Encoding.Default.GetString(AESEncrypt.TransformFinalBlock(buffer, 0, buffer.Length)) + IV));
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="cipherText">密文字节数组</param>
        /// <param name="strKey">密钥</param>
        /// <returns>返回解密后的字符串</returns>
        public static byte[] AESDecrypt(byte[] cipherText, string strKey)
        {
            SymmetricAlgorithm des = Rijndael.Create();
            des.Key = Encoding.UTF8.GetBytes(strKey);
            des.IV = _key1;
            des.Mode = CipherMode.ECB;
            des.BlockSize = 128;
            
            byte[] decryptBytes = new byte[cipherText.Length];
            MemoryStream ms = new MemoryStream(cipherText);
            CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read);
            cs.Read(decryptBytes, 0, decryptBytes.Length);
            cs.Close();
            ms.Close();
            return decryptBytes;
        }
        #endregion

        public static String EncryptIt(String s, byte[] key, byte[] IV)
        {
            String result;
            RijndaelManaged rijn = new RijndaelManaged();
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.Zeros;
            rijn.KeySize = 128;
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (ICryptoTransform encryptor = rijn.CreateEncryptor(key, IV))
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {
                            swEncrypt.Write(s);
                        }
                    }
                }
                result = Convert.ToBase64String(msEncrypt.ToArray());
            }
            rijn.Clear();
            return result;
        }

        public static String DecryptIt(String s, byte[] key, byte[] IV)
        {
            String result;
            RijndaelManaged rijn = new RijndaelManaged();
            rijn.Mode = CipherMode.ECB;
            rijn.Padding = PaddingMode.Zeros;
            rijn.KeySize = 128;
            using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(s)))
            {
                using (ICryptoTransform decryptor = rijn.CreateDecryptor(key, IV))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader swDecrypt = new StreamReader(csDecrypt))
                        {
                            result = swDecrypt.ReadToEnd();
                        }
                    }
                }
            }
            rijn.Clear();
            return result;
        }
    }
}
